﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Windows;
using System.Windows.Controls;

using BindingSource = System.Windows.Forms.BindingSource;

namespace Gamey.UI
{
    /// <summary>
    /// Interaction logic for MameControl.xaml
    /// </summary>
    public partial class MameControl : UserControl
    {
        GameyDataSet dataSet;
        BindingSource bindingSource;
        BackgroundWorker gameLoader;

        public event EventHandler LoadedGames;

        public MameControl()
        {
            this.dataSet = new GameyDataSet();

            this.bindingSource = new BindingSource
            {
                Filter = "(Locale IS NULL OR Locale = 'USA') AND Present"
            };

            this.gameLoader = new BackgroundWorker();
            this.gameLoader.DoWork += gameLoader_DoWork;
            this.gameLoader.RunWorkerCompleted += gameLoader_RunWorkerCompleted;

            InitializeComponent();
        }

        public void LoadGames()
        {
            if (!string.IsNullOrEmpty(Env.Settings.MamePath))
            {
                this.statusLabel.Content = "Loading games...";
                this.gameLoader.RunWorkerAsync();
            }
            else
            {
                OnLoadedGames();
            }
        }

        public void LaunchSelectedGame()
        {
            var selectedItem = this.dataGrid.SelectedItem as DataRowView;
            if (selectedItem == null)
            {
                return;
            }

            var selectedRow = selectedItem.Row as GameyDataSet.GamesRow;
            if (selectedRow == null)
            {
                return;
            }

            string mamePath = Env.Settings.MamePath;
            string name = selectedRow.Name;
            string mameDirectoryPath = Path.GetDirectoryName(mamePath);

            var mameProcessInfo = new ProcessStartInfo
            {
                FileName = mamePath,
                Arguments = name,
                WorkingDirectory = mameDirectoryPath
            };

            Process.Start(mameProcessInfo);
        }

        protected void OnLoadedGames()
        {
            this.statusBar.Items.Remove(this.progressBarItem);
            this.statusLabel.Content = "Ready";

            EventHandler loadedGamesHandler = LoadedGames;
            if (loadedGamesHandler != null)
            {
                loadedGamesHandler(this, EventArgs.Empty);
            }
        }

        void gameLoader_DoWork(object sender, DoWorkEventArgs e)
        {
            // Loading MAME games into in-memory DB.
            new MameXmlLoader().LoadGames(this.dataSet.Games);
        }

        void gameLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.bindingSource.DataSource = this.dataSet;
            this.bindingSource.DataMember = this.dataSet.Games.TableName;
            this.dataGrid.ItemsSource = this.bindingSource;

            OnLoadedGames();
        }

        private void dataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            LaunchSelectedGame();
        }

        private void searchTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            UpdateFilter();
        }

        private void minimumPlayersTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            UpdateFilter();
            HighlightMinimumPlayers();
        }

        private void minimumPlayersTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            HighlightMinimumPlayers();
        }

        private void HighlightMinimumPlayers()
        {
            // Using Dispatcher.BeginInvoke ensures that SelectAll gets called after any other
            // event handlers that might otherwise negate its effect.
            Dispatcher.BeginInvoke(new Action(() =>
            {
                this.minimumPlayersTextBox.SelectAll();
            }));
        }

        private void showAvailableGamesCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            UpdateFilter();
        }

        private void showLocalGamesCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            UpdateFilter();
        }

        private void UpdateFilter()
        {
            if (!IsVisible)
            {
                return;
            }

            var filters = new List<string>();

            if (this.searchTextBox.Text.Length > 0)
            {
                filters.Add(string.Format("Name LIKE '{0}%' OR Description LIKE '%{0}%'", this.searchTextBox.Text));
            }

            int minimumPlayers;
            if (int.TryParse(this.minimumPlayersTextBox.Text, out minimumPlayers) && minimumPlayers > 0)
            {
                filters.Add(string.Format("Players IS NOT NULL AND Players >= {0}", minimumPlayers));
            }

            if (this.showLocalGamesCheckBox.IsChecked ?? false)
            {
                filters.Add(string.Format("Locale IS NULL OR Locale = '{0}'", GetCurrentLocale()));
            }

            if (this.showAvailableGamesCheckBox.IsChecked ?? false)
            {
                filters.Add("Present");
            }

            this.bindingSource.Filter = string.Join(" AND ", filters.Select(f => string.Format("({0})", f)));
        }

        private MameLocale GetCurrentLocale()
        {
            // I'll implement this for real later.
            return MameLocale.USA;
        }
    }
}
